require 'fileutils'
require 'timeout'

class SubmitController < ApplicationController
  before_filter :authenticate

  def scores
    teams = Team.find(:all, :conditions => {:is_admin => "f"})
    @scores = []
    @title = "Scores"

    for team in teams
      points = team.submissions.select{|x| x.status == "SUCCESSFUL SUBMISSION"}.size
      @scores += [[team.name, points]]
    end
  end

  def submissions
    @submissions = Submission.find(:all, :conditions => {:team_id=> session['team'].id})
    @title = "Submissions"
  end

  def grading
    if session['team'].is_grading #only allow one submit at a time
      @refresh = true # refresh the page from application.rhtml
    else
      redirect_to :controller => "submit", :action => "submissions"
    end
  end

  def submit
    @title = "Submit"
    #only allow one submit at a time
    if Team.find(:first, :conditions => {:name => session['team'].name}).is_grading
        redirect_to :controller => "submit", :action => "grading"
    end
  end

  def submit_file
    team       = session['team']
    submission = Submission.new()

    submission.name      = params[:submit][:submission_for]
    submission.submitted = DateTime.now
    submission.file      = params[:submit][:file].read
    submission.language  = params[:submit][:submission_language]
    name                 = params[:submit][:submission_name]

    team.is_grading  = true 
    team.save

    pid = fork do #may decide to just remove and let the user hang for a bit  
      submission = check_code(submission, team.name, name)

      team.submissions << submission
      team.is_grading = false 
      team.save 

      exit 
    end

    Process.detach(pid)

    redirect_to :controller => "submit", :action => "grading"
  end


  private 

=begin
* Assumes that everything is clean and that no user has been able to put commands
* into the strings
=end
    def check_code(submission, team_name, name)
        if File.directory?("/tmp/"+team_name)
            FileUtils.rm_r("/tmp/"+team_name)
        end
        FileUtils.mkdir("/tmp/"+team_name)

        status = "FAILED"

        if submission.language == "Java" 
            status = save_grade_run_java(submission, team_name, name)
        elsif submission.language == "Haskell" 
            status= save_grade_run_haskell(submission, team_name)
        else
            status = "Unknown Language"
        end

        submission.status = status 
        return submission
    end

=begin
* Stop user from hurting the system
*   -parse file and look for threads
=end
    def save_grade_run_java(submission, team_name, name)
        # Write the file to the directory 
        #                /tmp/[team name]/[file name].java
        file = File.new("/tmp/"+team_name+"/"+name+".java", "w")
        file.puts(submission.file);
        file.flush()

        #get the problem dat file so that the contestant's code can read it 
        #TODO make this into an array that can be looped over
        problem_file = Problem.find(:first, :conditions => {:name => submission.name})

        IO.popen("javac /tmp/"+team_name+"/"+name+".java"){}

        if File.exists?("/tmp/"+team_name+"/"+name+".class")

            file = File.new("/tmp/"+team_name+"/"+submission.name+".dat","w")
            file.puts(problem_file.input)
            file.flush()

            Dir.chdir("/tmp/"+team_name)

            # Compile the program 
            #                    java -cp /tmp/[team name] [file name]
            process = IO.popen( "java -cp /tmp/"+team_name+" "+name)
            pid     = process.pid 
            sleep(5)

            running = IO.popen("ps | grep #{pid.to_s}").read().include?("java -cp")

            if running 
                IO.popen("kill #{pid}")
                return "RAN OUT OF TIME"
            end
        else
            return    "FAILED TO COMPILE"
        end

        file = File.new("/tmp/"+team_name+"/correct.out", "w")
        file.puts(problem_file.output)
        file.flush

        # Check to see if the program has the correct solution
        if File.exists?("/tmp/"+team_name+"/"+submission.name+".out")
            diff_status = IO.popen("diff /tmp/"+team_name+"/correct.out /tmp/"+team_name+"/"+submission.name+".out")
            if diff_status.readlines != []
                return "INCORRECT OUTPUT"
            else
                return "SUCCESSFUL SUBMISSION"
            end
        else
            return "NO OUTPUT FILE"
        end
    end

=begin 
*Do some grading for haskell
=end
  def save_grade_run_haskell(submission, team_name)
    file = File.new("/tmp/"+team_name+"/"+submission.name+".hs", "w")
    file.puts(submission.file);
  end
end
